package xnj.lazydog.btcontroller.HexStringUtils;

import java.io.UnsupportedEncodingException;
import java.util.Locale;

/**
 *    功能： HEX数据 和 字符串 之间的转换
 *
 *     1.bytes 和 String 的互转，以指定的charSet    0x30,0x31,0x32,0x33 <==> "0123"
 *     2.bytes 和 HEX型String 的互转              0x30,0x31,0x32,0x33 <==> "30 31 32 33"
 */
public class HexStr {

    public static String [] turn_line_list = new String[]{""+'\n',""+'\r',""+'\r'+'\n',""};
    public static int turn_line_replace = 0;

    public static final String CHARSET_UTF_8 = "UTF-8";
    public static final String CHARSET_ASCII = "ASCII";
    public static final String CHARSET_GBK = "GBK";
    public static final String CHARSET_UNICODE = "Unicode";
    public static final String CHARSET_GB2312 = "GB2312";
    public static String charset = CHARSET_UTF_8;

    public static int TURN_LINE_NO_CHANGE = 0;
    public static int TURN_LINE_TO_R = 1;
    public static int TURN_LINE_TO_R_N = 2;
    public static int TURN_LINE_REMOVE = 3;


    /**
     * 设置换行符的替换符号
     * @param turnLine
     */

    public static void setTurnLine(int turnLine)
    {
        turn_line_replace = turnLine;
    }

    /**
     * 替换换行符
     * @param s
     * @return
     */

    public static String replaceTurnLine(String s)
    {
        return s.replace("" + '\n', turn_line_list[turn_line_replace]);
    }

    /**
     *
     * 指定用于转换的字符集
     * @param charSet:  字符集
     */
    public static void setCharset(String charSet)
    {
        charset = charSet;
    }


    /**
     * 获取字符串的字节数组表示
     * @param text 待转换的字符串
     * @return
     */
    public static byte[] str2Bytes(String text)
    {
        try {
            return text.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return text.getBytes();
        }
    }

    /**
     * 获取字符串表示的字节数组
     * @param string 待转换的字符串
     * @return
     */
    public static byte[] hexStr2Bytes(String string)
    {
        if(!isHexFormatOK(string))
            string = formatHexString(string);

        int l = (string.length()+1)/3;

        byte[] ba = new byte[l];

        for(int i=0;i<l;i++)
        {
            ba[i]= (byte)((getHexFromChar(string.charAt(i*3))<<4)|(getHexFromChar(string.charAt(i*3+1))));
        }
        return ba;
    }


    /**
     * 检查该字符串是否符合HexString格式，如 "5A A5 "
     * @param src 字符串，格式以三个字符为一个单位
     * @return
     */
    public static boolean isHexFormatOK(String src)
    {
        if(src.length()==0)
            return true;

        for(int i=0;i<src.length();i++)
        {
            if(i%3==0||i%3==1)
            {
                if(!isHexCode(src.charAt(i)))
                    return false;
            }
            if(i%3==2)
            {
                if(src.charAt(i)!=' ')
                    return false;
            }
        }
        return  true;
    }


    /**
     * @param bytes 待转化的字节数组
     * @param length 字节数组中指定长度
     * @return 返回转化得到的字符串，如果不支持指定的字符集，则返回默认的字符集
     */
    public static String bytes2String(byte[] bytes,int off,int length)
    {
        try {
            return new String(bytes,off,length,charset);
        } catch (UnsupportedEncodingException e) {
            return new String(bytes,off,length);
        }
    }

    /**
     * @param bytes 待转化的字节数组
     * @return 返回转化得到的字符串，如果不支持指定的字符集，则返回默认的字符集
     */
    public static String bytes2String(byte[] bytes)
    {
        try {
            return new String(bytes,charset);
        } catch (UnsupportedEncodingException e) {
            return new String(bytes);
        }
    }

    /**
     * @param bytes 待转化的字节数组
     * @param length 字节数组中指定长度
     * @return 返回xx得到的字符串，如果不支持指定的字符集，则返回默认的字符集
     */
    public static String bytes2HexStr(byte[] bytes,int off,int length)
    {
        if (bytes==null||bytes.length==0)
            return "";
        String s="";

        if(off+length>bytes.length)
            return "";

        for(int i=off;i<off+length;i++) {
            s=s.concat(String.format(Locale.getDefault(),"%02X ",bytes[i]));
        }
        return s;
    }

    /**
     * @param bytes 待转化的字节数组
     * @return 返回xx得到的字符串，如果不支持指定的字符集，则返回默认的字符集
     */
    public static String bytes2HexStr(byte[] bytes)
    {
        if (bytes==null||bytes.length==0)
            return "";
        String s="";

        for(byte b:bytes) {
            s=s.concat(String.format(Locale.getDefault(),"%02X ",b));
        }
        return s;
    }

    /**
     * 将输入的字符串规范化为符合HexString格式，如 "5A A5 "
     * @param src 待规范化的字符串，格式以三个字符为一个单位
     * @return
     */
    public static String formatHexString(String src)
    {
        String cs="";
        String ret="";
        for(int i=0;i<src.length();i++)
        {
            if(isHexCode(src.charAt(i)))
                cs=cs.concat(src.charAt(i)+"");
        }

        for(int i=0;i<cs.length();i++)
        {
            ret = ret.concat(""+cs.charAt(i));
            if(i%2==1) {
                ret = ret.concat(" ");
            }
        }
        return ret;
    }


    public static boolean isHexCode(char c)
    {
        boolean isOk = false;
        if(c>='0'&&c<='9')
            isOk =true;
        if(c>='a'&&c<='f')
            isOk = true;
        if(c>='A'&&c<='F')
            isOk = true;
        return isOk;
    }

    public static int getHexFromChar(char c)
    {
        if(c>='0'&&c<='9')
            return c-'0';

        if(c>='a'&&c<='f')
            return c-'a'+10;
        if(c>='A'&&c<='F')
            return c-'A'+10;
        return -1;
    }

    public static boolean hasOtherChar(CharSequence s)
    {
        char c;
        for(int i=0;i<s.length();i++)
        {

            c = s.charAt(i);
            if(!(getHexFromChar(c)>=0||c==' '))
            {
                return true;
            }
        }
        return false;
    }

    public static boolean hasLowerCase(CharSequence s)
    {
        char c;
        for(int i=0;i<s.length();i++)
        {

            c = s.charAt(i);
            if(c>='a'&&c<='f')
            {
                return true;
            }
        }
        return false;
    }


    public static int numberFromString(CharSequence s,int max,int min)
    {
        int f;
        if(s==null)
            return -1;
        try {
            f = Integer.parseInt(s.toString());
        }catch (NumberFormatException e)
        {
            return  -2;
        }
        if(f<min)
            f=-3;
        if(f>max)
            f=-4;
        return f;
    }

}
